package aes.client;

import java.awt.*;
import java.awt.event.*;
import java.io.IOException;
import java.util.*;

import javax.swing.*;
import javax.swing.Timer;
import javax.swing.border.*;

import common.*;

public class ExamExecutionFormUI extends JPanel implements ActionListener, Observer {

	/**
	 * 
	 */
	private static final long serialVersionUID = -777378506801078985L;
	private ClientUI ui;
	private Client c;
	private JLabel lblAesTitle;
	private JTextField txtQuestion;
	private JRadioButton rdbtn1;
	private JRadioButton rdbtn2;
	private JRadioButton rdbtn3;
	private JRadioButton rdbtn4;
	private ButtonGroup group;
	private JButton btnPrev;
	private JButton btnNext;
	private JButton btnBack;
	private JButton btnFinish;
	private JLabel lblTime;
	
	private StudentExam se;
	private int curQuest = 0;
	private int curQuestInd = 0;
	private int studentId;
	private Timer timer;
	private int avaliableTime = 0;
	private JLabel lblMark;
	private JLabel lblNotes;
	private JTextField txtMark;
	private JTextField txtNotes;
	private JButton btnGrade;
	private JLabel lblCheating;
	private JLabel lblComments;
	
	private boolean showAnswers = false;
	
	/**
	 * Constructor
	 * @param c Client object reference
	 * @param ui ClientUI object reference
	 */
	public ExamExecutionFormUI(Client c,ClientUI ui){
		super();
		this.c = c;
		this.ui = ui;
		
		c.addObserver(this);
		GridBagLayout gridBagLayout = new GridBagLayout();
		setLayout(gridBagLayout);
		
		JPanel panel = new JPanel();
		panel.setBorder(new LineBorder(new Color(0, 0, 0), 2, true));
		panel.setPreferredSize(new Dimension(600,400));
		panel.setSize(new Dimension(600,400));
		
		GridBagConstraints gbc_panel = new GridBagConstraints();
		gbc_panel.fill = GridBagConstraints.HORIZONTAL;
		gbc_panel.insets = new Insets(5, 0, 5, 0);
		gbc_panel.gridx = 0;
		gbc_panel.gridy = 0;
		add(panel,gbc_panel);
		GridBagLayout gbl_panel = new GridBagLayout();
		gbl_panel.rowWeights = new double[]{0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0};
		gbl_panel.rowHeights = new int[]{0, 0, 0, 0, 0, 0, 0, 56, 0};
		gbl_panel.columnWidths = new int[]{70, 37, 177, 0};
		gbl_panel.columnWeights = new double[]{0.0, 0.0, 1.0, 0.0};
		panel.setLayout(gbl_panel);
		
		lblAesTitle = new JLabel("Exam Execution");
		lblAesTitle.setHorizontalAlignment(SwingConstants.CENTER);
		lblAesTitle.setBounds(7, 10, 70, 17);
		lblAesTitle.setFont(new Font("Tahoma", Font.BOLD, 14));
		
		GridBagConstraints gbc_lblAesTitle = new GridBagConstraints();
		gbc_lblAesTitle.gridwidth = 4;
		gbc_lblAesTitle.fill = GridBagConstraints.BOTH;
		gbc_lblAesTitle.insets = new Insets(5, 0, 5, 0);
		gbc_lblAesTitle.gridx = 0;
		gbc_lblAesTitle.gridy = 0;
		panel.add(lblAesTitle, gbc_lblAesTitle);
		
		lblComments = new JLabel("");
		GridBagConstraints gbc_lblComments = new GridBagConstraints();
		gbc_lblComments.gridwidth = 3;
		gbc_lblComments.anchor = GridBagConstraints.SOUTHWEST;
		gbc_lblComments.insets = new Insets(0, 10, 5, 5);
		gbc_lblComments.gridx = 0;
		gbc_lblComments.gridy = 1;
		panel.add(lblComments, gbc_lblComments);
		
		lblCheating = new JLabel("Cheating Warning !!!");
		lblCheating.setFont(new Font("Tahoma", Font.BOLD, 11));
		lblCheating.setHorizontalAlignment(SwingConstants.RIGHT);
		lblCheating.setForeground(Color.RED);
		GridBagConstraints gbc_lblCheating = new GridBagConstraints();
		gbc_lblCheating.anchor = GridBagConstraints.EAST;
		gbc_lblCheating.insets = new Insets(0, 5, 5, 5);
		gbc_lblCheating.gridx = 2;
		gbc_lblCheating.gridy = 7;
		panel.add(lblCheating, gbc_lblCheating);
		
		lblTime = new JLabel("Time left: 00:00:00");
		GridBagConstraints gbc_lblTime = new GridBagConstraints();
		gbc_lblTime.anchor = GridBagConstraints.EAST;
		gbc_lblTime.insets = new Insets(0, 0, 5, 10);
		gbc_lblTime.gridx = 3;
		gbc_lblTime.gridy = 1;
		panel.add(lblTime, gbc_lblTime);
		
		JLabel lblQuestion = new JLabel("Question:");
		GridBagConstraints gbc_lblQuestion = new GridBagConstraints();
		gbc_lblQuestion.anchor = GridBagConstraints.WEST;
		gbc_lblQuestion.insets = new Insets(0, 10, 5, 5);
		gbc_lblQuestion.gridx = 0;
		gbc_lblQuestion.gridy = 2;
		panel.add(lblQuestion, gbc_lblQuestion);
		
		txtQuestion = new JTextField();
		txtQuestion.setEditable(false);
		GridBagConstraints gbc_txtQuestion = new GridBagConstraints();
		gbc_txtQuestion.gridwidth = 3;
		gbc_txtQuestion.anchor = GridBagConstraints.WEST;
		gbc_txtQuestion.insets = new Insets(0, 0, 5, 10);
		gbc_txtQuestion.fill = GridBagConstraints.HORIZONTAL;
		gbc_txtQuestion.gridx = 1;
		gbc_txtQuestion.gridy = 2;
		panel.add(txtQuestion, gbc_txtQuestion);
		txtQuestion.setColumns(10);
		
		rdbtn1 = new JRadioButton("Answer1");
		rdbtn1.addActionListener(this);
		GridBagConstraints gbc_rdbtn1 = new GridBagConstraints();
		gbc_rdbtn1.anchor = GridBagConstraints.WEST;
		gbc_rdbtn1.gridwidth = 4;
		gbc_rdbtn1.insets = new Insets(0, 10, 5, 0);
		gbc_rdbtn1.gridx = 0;
		gbc_rdbtn1.gridy = 3;
		panel.add(rdbtn1, gbc_rdbtn1);
		
		rdbtn2 = new JRadioButton("Answer 2");
		rdbtn2.addActionListener(this);
		GridBagConstraints gbc_rdbtn2 = new GridBagConstraints();
		gbc_rdbtn2.anchor = GridBagConstraints.WEST;
		gbc_rdbtn2.gridwidth = 4;
		gbc_rdbtn2.insets = new Insets(0, 10, 5, 0);
		gbc_rdbtn2.gridx = 0;
		gbc_rdbtn2.gridy = 4;
		panel.add(rdbtn2, gbc_rdbtn2);
		
		rdbtn3 = new JRadioButton("Answer 3");
		rdbtn3.addActionListener(this);
		GridBagConstraints gbc_rdbtn3 = new GridBagConstraints();
		gbc_rdbtn3.gridwidth = 4;
		gbc_rdbtn3.anchor = GridBagConstraints.WEST;
		gbc_rdbtn3.insets = new Insets(0, 10, 5, 0);
		gbc_rdbtn3.gridx = 0;
		gbc_rdbtn3.gridy = 5;
		panel.add(rdbtn3, gbc_rdbtn3);
		
		rdbtn4 = new JRadioButton("Answer 4");
		rdbtn4.addActionListener(this);
		GridBagConstraints gbc_rdbtn4 = new GridBagConstraints();
		gbc_rdbtn4.anchor = GridBagConstraints.WEST;
		gbc_rdbtn4.gridwidth = 4;
		gbc_rdbtn4.insets = new Insets(0, 10, 5, 0);
		gbc_rdbtn4.gridx = 0;
		gbc_rdbtn4.gridy = 6;
		panel.add(rdbtn4, gbc_rdbtn4);
		
		//Group the radio buttons.
	    group = new ButtonGroup();
	    group.add(rdbtn1);
	    group.add(rdbtn2);
	    group.add(rdbtn3);
	    group.add(rdbtn4);
		
		btnPrev = new JButton("Prev");
		btnPrev.setIcon(new ImageIcon(ExamExecutionFormUI.class.getResource("/aes/client/images/Previous.png")));
		btnPrev.addActionListener(this);
		
		btnGrade = new JButton("Accept");
		btnGrade.addActionListener(this);
		btnGrade.setIcon(new ImageIcon(ExamExecutionFormUI.class.getResource("/aes/client/images/accept.png")));
		btnGrade.setSelectedIcon(null);
		GridBagConstraints gbc_btnGrade = new GridBagConstraints();
		gbc_btnGrade.anchor = GridBagConstraints.SOUTHEAST;
		gbc_btnGrade.insets = new Insets(0, 0, 10, 10);
		gbc_btnGrade.gridx = 3;
		gbc_btnGrade.gridy = 8;
		panel.add(btnGrade, gbc_btnGrade);
		GridBagConstraints gbc_btnPrev = new GridBagConstraints();
		gbc_btnPrev.anchor = GridBagConstraints.WEST;
		gbc_btnPrev.insets = new Insets(0, 10, 5, 5);
		gbc_btnPrev.gridx = 0;
		gbc_btnPrev.gridy = 7;
		panel.add(btnPrev, gbc_btnPrev);
		
		lblMark = new JLabel("Grade:");
		GridBagConstraints gbc_lblMark = new GridBagConstraints();
		gbc_lblMark.anchor = GridBagConstraints.WEST;
		gbc_lblMark.insets = new Insets(0, 5, 5, 5);
		gbc_lblMark.gridx = 1;
		gbc_lblMark.gridy = 7;
		panel.add(lblMark, gbc_lblMark);
		
		btnNext = new JButton("Next");
		btnNext.setIcon(new ImageIcon(ExamExecutionFormUI.class.getResource("/aes/client/images/Next.png")));
		btnNext.addActionListener(this);
		
		txtMark = new JTextField();
		GridBagConstraints gbc_txtMark = new GridBagConstraints();
		gbc_txtMark.anchor = GridBagConstraints.WEST;
		gbc_txtMark.insets = new Insets(0, 0, 5, 5);
		gbc_txtMark.gridx = 2;
		gbc_txtMark.gridy = 7;
		panel.add(txtMark, gbc_txtMark);
		txtMark.setColumns(3);
		GridBagConstraints gbc_btnNext = new GridBagConstraints();
		gbc_btnNext.insets = new Insets(0, 0, 5, 10);
		gbc_btnNext.anchor = GridBagConstraints.EAST;
		gbc_btnNext.gridx = 3;
		gbc_btnNext.gridy = 7;
		panel.add(btnNext, gbc_btnNext);
		
		btnBack = new JButton("Back");
		btnBack.addActionListener(this);
		btnBack.setIcon(new ImageIcon(ExamExecutionFormUI.class.getResource("/aes/client/images/back.png")));
		GridBagConstraints gbc_btnBack = new GridBagConstraints();
		gbc_btnBack.anchor = GridBagConstraints.SOUTHWEST;
		gbc_btnBack.insets = new Insets(0, 10, 10, 5);
		gbc_btnBack.gridx = 0;
		gbc_btnBack.gridy = 8;
		panel.add(btnBack, gbc_btnBack);
		
		btnFinish = new JButton("Finish");
		btnFinish.addActionListener(this);
		
		lblNotes = new JLabel("Notes:");
		GridBagConstraints gbc_lblNotes = new GridBagConstraints();
		gbc_lblNotes.anchor = GridBagConstraints.NORTHEAST;
		gbc_lblNotes.insets = new Insets(3, 5, 0, 5);
		gbc_lblNotes.gridx = 1;
		gbc_lblNotes.gridy = 8;
		panel.add(lblNotes, gbc_lblNotes);
		
		txtNotes = new JTextField();
		GridBagConstraints gbc_txtNotes = new GridBagConstraints();
		gbc_txtNotes.anchor = GridBagConstraints.NORTHWEST;
		gbc_txtNotes.insets = new Insets(0, 0, 10, 5);
		gbc_txtNotes.fill = GridBagConstraints.BOTH;
		gbc_txtNotes.gridx = 2;
		gbc_txtNotes.gridy = 8;
		panel.add(txtNotes, gbc_txtNotes);
		txtNotes.setColumns(10);
		btnFinish.setIcon(new ImageIcon(ExamExecutionFormUI.class.getResource("/aes/client/images/Save.png")));
		GridBagConstraints gbc_btnFinish = new GridBagConstraints();
		gbc_btnFinish.insets = new Insets(0, 0, 10, 10);
		gbc_btnFinish.anchor = GridBagConstraints.SOUTHEAST;
		gbc_btnFinish.gridx = 3;
		gbc_btnFinish.gridy = 8;
		panel.add(btnFinish, gbc_btnFinish);
				
		// Initialize timer.
		timer=new Timer(1000, this);
		
		// Disable grade editing.
		EnableMarkEdit(false);
		
		btnFinish.setVisible(false);
		btnGrade.setVisible(false);
	}
	
	/**
	 * Load exam
	 * @param code Exam code
	 * @param studentId Student Id
	 */
	public void loadExam(String code, int studentId) {
		this.studentId = studentId;
		CommandMessage msg = new CommandMessage(CommandMessage.GET_STUDENT_EXAM,new Object[] {code, studentId});
		try {
			c.sendToServer(msg);
		} catch (IOException e1) {
			e1.printStackTrace();
		}
	}
	
	/**
	 * Server message received event handler
	 */
	@SuppressWarnings("static-access")
	@Override
	public void update(Observable arg0, Object arg1) {
		if (arg1 instanceof CommandMessage) {
			CommandMessage ms=(CommandMessage)arg1;
			if (ms.getCommand().equals(CommandMessage.ACKNOWLEDGE_MESSAGE) && ((String)ms.getParams()[0]).equals(CommandMessage.GET_STUDENT_EXAM)) {
				if (ms.getParams()[1] == null) {
					// Not found.
					ui.ShowLastScreen();
					timer.stop();
					timer.removeActionListener(this);
					timer = null;
				}
				else {
					// Exam loaded.
					se = (StudentExam)ms.getParams()[1];
					if (se.getQuestions().length > 0)
						curQuest = se.getQuestions()[0].getId();
					if (ui.getUser() instanceof Teacher)
						lblComments.setText(((AutoExamExecution)se.getExam()).getTeachersNotes());
					if (ui.getUser() instanceof Student)
						lblComments.setText(((AutoExamExecution)se.getExam()).getStudentsNotes());
					if (se.getTimeFinished() != null) {
						showAnswers = true;
						btnFinish.setVisible(false);
						rdbtn1.setEnabled(false);
						rdbtn2.setEnabled(false);
						rdbtn3.setEnabled(false);
						rdbtn4.setEnabled(false);
						lblTime.setVisible(false);
						lblAesTitle.setText("Grade: " + se.getGrade());	
					}
					else {
						timer.stop();
						avaliableTime = se.getExam().getActualTime();
						if (avaliableTime > 0) {
							timer.start();
							UpdateClock();
							btnFinish.setVisible(ui.getUser().getId() == se.getStudentId());
						}
						else {
							showAnswers = true;
							btnFinish.setVisible(false);
							rdbtn1.setEnabled(false);
							rdbtn2.setEnabled(false);
							rdbtn3.setEnabled(false);
							rdbtn4.setEnabled(false);
							lblTime.setVisible(false);
							lblAesTitle.setText("Grade: " + se.getGrade());	
						}
					}
					// If exam teacher and not checked allow checking.
					if (se.getExam().getExecTeacherID() == ui.getUser().getId() && !se.isApproved()) {
						showAnswers = true;
						EnableMarkEdit(true);
						txtMark.setText(Integer.toString(se.getGrade()));
						txtNotes.setText(se.getNotes());
						btnGrade.setVisible(true);
						lblCheating.setVisible(se.isCheater());
					}
					showQuestion(curQuest);
				}
			}
			else if (ms.getCommand().equals(CommandMessage.ACKNOWLEDGE_MESSAGE) && ((String)ms.getParams()[0]).equals(CommandMessage.SUBMIT_STUDENT_EXAM)) {
				int grade = (ms.getParams()[1] == null)? -1 : Integer.parseInt(ms.getParams()[1].toString());
				if (grade < 0) {
					ui.ShowMessageBox("Error", "Can't submit your answers.", JOptionPane.ERROR_MESSAGE);
				}
				else {
					timer.stop();
					timer.removeActionListener(this);
					timer = null;
					ui.ShowMessageBox("Message", "Your answers were saved successfully.", JOptionPane.INFORMATION_MESSAGE);
					ui.ShowLastScreen();
				}
			}
			else if (ms.getCommand().equals(CommandMessage.ACKNOWLEDGE_MESSAGE) && ((String)ms.getParams()[0]).equals(CommandMessage.CONFIRM_STUDENT_GRADE)) {
				boolean res = (ms.getParams()[1] == null)? false : Boolean.parseBoolean(ms.getParams()[1].toString());
				if (!res) {
					ui.ShowMessageBox("Error", "Can't confirm grade.", JOptionPane.ERROR_MESSAGE);
				}
				else {
					ui.ShowMessageBox("Message", "The grade was successfully confirmed.", JOptionPane.INFORMATION_MESSAGE);
					ui.SetContent(ui.GRADE_APPROVAL_SCREEN);
					ExamCheckingUI panel= ((ExamCheckingUI)ui.getContentPane());
					panel.setExamExecutionCode(se.getExam().getCode());
					panel.loadExams();
				}
			}
			else if (ms.getCommand().equals(CommandMessage.LOCK_EXAM_EXECUTION)) {
				String code = ms.getParams()[0].toString();
				if (se.getExam().getCode().equals(code) && timer.isRunning()) {
					// Exam was locked. 
					c.deleteObserver(this);
					// Stop timer.
					timer.stop();
					timer.removeActionListener(this);
					timer = null;
					// Submit answers.
					SubmitAnswers(false);
					// Inform user.
					ui.ShowMessageBox("Message", "Exam was locked.", JOptionPane.INFORMATION_MESSAGE);
					ui.ShowLastScreen();
				}
			}
			else if (ms.getCommand().equals(CommandMessage.ACCEPT_OR_REJECT_ADDITIONAL_TIME)) {
				String code = ms.getParams()[1].toString();
				int additionalTime = Integer.parseInt(ms.getParams()[0].toString());
				if (se.getExam().getCode().equals(code) && timer.isRunning()) {
					avaliableTime += additionalTime * 60;
					ui.ShowMessageBox("Message", "You have additional " + additionalTime + " minutes to solve the exam.", JOptionPane.INFORMATION_MESSAGE);
				}
			}
		}
	}
	

	/**
	 * Action performed event handler
	 */
	@SuppressWarnings("static-access")
	@Override
	public void actionPerformed(ActionEvent arg0) {
		if (arg0.getSource().equals(btnBack)) {
			// Back.
			if (ui.getLastScreen() == ui.GRADE_APPROVAL_SCREEN) {
				ui.SetContent(ui.GRADE_APPROVAL_SCREEN);
				ExamCheckingUI panel= ((ExamCheckingUI)ui.getContentPane());
				panel.setExamExecutionCode(se.getExam().getCode());
				panel.loadExams();
			}
			else 
				ui.ShowLastScreen();
		}
		else if (arg0.getSource().equals(btnNext)) {
			// Next question.
			curQuest = se.getQuestions()[curQuestInd + 1].getId();
			showQuestion(curQuest);
		}
		else if (arg0.getSource().equals(btnPrev)) {
			// Previous question.
			curQuest = se.getQuestions()[curQuestInd - 1].getId();
			showQuestion(curQuest);
		}
		else if (arg0.getSource().equals(rdbtn1)) {
			// First answer was choosed.
			setAnswer(1);
		}
		else if (arg0.getSource().equals(rdbtn2)) {
			// Second answer was choosed.
			setAnswer(2);
		}
		else if (arg0.getSource().equals(rdbtn3)) {
			// Third answer was choosed.
			setAnswer(3);
		}
		else if (arg0.getSource().equals(rdbtn4)) {
			// Fourth answer was choosed.
			setAnswer(4);
		}
		else if (arg0.getSource().equals(btnFinish)) {
			// Submit answers.
			SubmitAnswers(true);
		}
		else if (arg0.getSource().equals(btnGrade)) {
			// Approve grade.
			ApproveGrade();
		}
		else if (arg0.getSource().equals(timer)) {
			// Timer tick event occured.
			avaliableTime--;
			UpdateClock();
		}
	}
	
	/**
	 * Save student answer
	 * @param answer Selected answer
	 */
	private void setAnswer(int answer) {
		if (se.getAnswers() != null) {
			for (StudentAnswer sa : se.getAnswers()) {
				if (sa.getQuestionId() == curQuest) {
					sa.setAnswer(answer);
					return;
				}
			}
		}
		StudentAnswer sa = new StudentAnswer();
		sa.setStudentId(studentId);
		sa.setExamCode(se.getExam().getCode());
		sa.setQuestionId(curQuest);
		sa.setAnswer(answer);
		StudentAnswer[] arr = new StudentAnswer[(se.getAnswers()==null)? 1: se.getAnswers().length + 1];
		if (arr.length > 1) {
			// Copy array.
			for (int i=0; i<se.getAnswers().length; i++) {
				arr[i] = se.getAnswers()[i];
			}
		}
		arr[se.getAnswers().length] = sa;
		se.setAnswers(arr);
	}
	
	/**
	 * Clear all fields
	 */
	private void clearFields() {
		txtQuestion.setText("");
		group.clearSelection();
		rdbtn1.setText("");
		rdbtn2.setText("");
		rdbtn3.setText("");
		rdbtn4.setText("");
	}
	
	/**
	 * Show specific question
	 * @param number Question ID
	 */
	private void showQuestion(int number) {
		// find question
		curQuestInd = 0;
		clearFields();
		for(Question q : se.getQuestions()) {
			if (q.getId() == number) {
				txtQuestion.setText(q.getQuestion());
				rdbtn1.setText(q.getAnswers()[0]);
				rdbtn2.setText(q.getAnswers()[1]);
				rdbtn3.setText(q.getAnswers()[2]);
				rdbtn4.setText(q.getAnswers()[3]);
				
				// Select relevant answer.
				if (se.getAnswers() != null) {
					for (StudentAnswer sa : se.getAnswers()) {
						if (sa.getQuestionId() == number) {
							switch (sa.getAnswer()) {
								case 1:
									rdbtn1.setSelected(true);
									break;
								case 2:
									rdbtn2.setSelected(true);
									break;
								case 3:
									rdbtn3.setSelected(true);
									break;
								case 4:
									rdbtn4.setSelected(true);
									break;
							}
							break;
						}
					}
				}
				if (showAnswers) {
					// Show correct answer.
					rdbtn1.setBackground((q.getCorrectAnswer() == 1)? ((rdbtn1.isSelected())? Color.GREEN : Color.RED) : new Color(240, 240, 240));
					rdbtn2.setBackground((q.getCorrectAnswer() == 2)? ((rdbtn2.isSelected())? Color.GREEN : Color.RED) : new Color(240, 240, 240));
					rdbtn3.setBackground((q.getCorrectAnswer() == 3)? ((rdbtn3.isSelected())? Color.GREEN : Color.RED) : new Color(240, 240, 240));
					rdbtn4.setBackground((q.getCorrectAnswer() == 4)? ((rdbtn4.isSelected())? Color.GREEN : Color.RED) : new Color(240, 240, 240));
				}
				
				btnNext.setEnabled(curQuestInd < se.getQuestions().length - 1);
				btnPrev.setEnabled(curQuestInd > 0);
				return;
			}
			curQuestInd++;
		}
	}

	/**
	 * Update clock
	 */
	@SuppressWarnings("static-access")
	private void UpdateClock() {
		if (ui.getUser() instanceof Student) {
			int seconds = avaliableTime % 60;
			int minutes = (avaliableTime / 60) % 60;
			int hours = avaliableTime / 3600;
			
			lblTime.setText("Time left: " + hours + ":" + String.format("%02d",minutes) + ":" + String.format("%02d", seconds));
			lblTime.setForeground((avaliableTime < 60)? Color.RED : Color.BLACK);
			
			if (avaliableTime < 1) {
				// Late.
				ui.ShowMessageBox("Message", "Your time has gone.", JOptionPane.INFORMATION_MESSAGE);
				timer.stop();
				se.setTimeFinished(null);
				// Sumbit exam.
				SubmitAnswers(false);
			}
		}
	}
	
	/**
	 * Send answers to the server
	 */
	private void SubmitAnswers(boolean hasFinished) {
		CommandMessage msg = new CommandMessage(CommandMessage.SUBMIT_STUDENT_EXAM,new Object[] {se, hasFinished});
		try {
			c.sendToServer(msg);
		} catch (IOException e1) {
			e1.printStackTrace();
		}
	}
	
	/**
	 * Enable/Disable mark editing
	 * @param enable
	 */
	private void EnableMarkEdit(boolean enable) {
		this.lblMark.setVisible(enable);
		this.lblNotes.setVisible(enable);
		this.txtMark.setVisible(enable);
		this.txtNotes.setVisible(enable);
		this.lblCheating.setVisible(false);
	}
	
	/**
	 * Confirm/Change grade.
	 */
	@SuppressWarnings("static-access")
	private void ApproveGrade() {
		int grade = Integer.parseInt(txtMark.getText().trim());
		if (txtMark.getText().trim().length() < 1 || grade < 0) {
			ui.ShowMessageBox("Error", "Wrong grade provided", JOptionPane.ERROR_MESSAGE);
			return;
		}
		CommandMessage msg = new CommandMessage(CommandMessage.CONFIRM_STUDENT_GRADE,new Object[] {se.getExam().getCode(), se.getStudentId(), Integer.parseInt(txtMark.getText().trim()), txtNotes.getText()});
		try {
			c.sendToServer(msg);
		} catch (IOException e1) {
			e1.printStackTrace();
		}
	}
}
